#!/bin/bash
##################################################
# 脚本说明: 服务安装脚本，包括解压安装包、修改配置文件
# 前提条件: 主脚本运行无误
# 启动方法：由主节点 run.sh 调用
# 参数说明: source ${PROGDIR}/conf/init.cfg
#-------------------------------------------------
# 创建: tangxin  2021/6/10
# 修改:
# 修改时间   修改人   修改说明
#
#
##################################################

## 获取上下文路径、本脚本名
readonly PROGDIR=$(readlink -m $(dirname $0))
readonly PROGNAME=$(basename $0)
readonly HOSTNAME=`hostname`

## 读取配置文件
source $PROGDIR/conf/init.cfg

## 打印输出函数，输出内容格式化；调用方法：format_print 级别 "输出内容"
function format_print(){
  LEVEL=$1
  INFO=$2
  if [[ $LEVEL == 'INFO' ]];then
    echo -e "`date "+%Y-%m-%d %H:%M:%S"` [INFO] ${INFO}" 
  elif [[ $LEVEL == 'FAILED' ]];then
    echo -e "`date "+%Y-%m-%d %H:%M:%S"` \e[31m[FAILED] ${INFO}\e[0m" 
  elif [[ $LEVEL == 'SUCCESS' ]];then
    echo -e "`date "+%Y-%m-%d %H:%M:%S"` \e[32m[SUCCESSFUL] ${INFO}\e[0m" 
  fi
}

## 必须使用hadoop用户执行
if [ $USER != "hadoop" ]; then
  format_print FAILED "Must run as hadoop"
  exit 1
fi

## 检查状态
function checkState(){
  SERVER_NAME=$1
  STATE=$2
  if [[ $STATE == "1" ]];then
    format_print SUCCESS "$SERVER_NAME on $HOST Install Successful"
  elif [[ $STATE == "2" ]];then
    format_print FAILED "$SERVER_NAME on $HOST Install FAILED"
    exit 1
  elif [[ $STATE == "3" ]];then
    format_print FAILED "Directory $HADOOP_DIR/${!SERVER_NAME_VERSION} already exists "
  else
    format_print FAILED "$SERVER_NAME don't need to install on host $HOSTNAME,Please check ${SERVER_NAME}_HOSTS" in $PROGDIR/init.cfg 
    exit 1
  fi
}

## 安装 Server 模板
## 安装 Server,设置环境变量
function installSERVER_NAME(){
  SERVER_NAME="SERVER_NAME"
  source $PROGDIR/conf/init.cfg
  format_print INFO "########## 安装 $SERVER_NAME"
  format_print INFO "${SERVER_NAME}_HOSTS Is : ${!SERVER_NAME_HOSTS}"

  ## 判断服务对应的主机是否配置
  if [[ ! -n ${!SERVER_NAME_HOSTS} ]];then
    format_print INFO "${SERVER_NAME}_HOSTS not set"
  fi

  ## 判断主机是否需要安装
  STATE=0
  for HOST in ${!SERVER_NAME_HOSTS}
  do
    if [[ $HOSTNAME == $HOST ]];then
      format_print INFO "$HOSTNAME 需要安装 $SERVER_NAME"
      if [[ ! -d $HADOOP_DIR/${!SERVER_NAME_VERSION} ]];then
        format_print INFO "$HADOOP_DIR/${!SERVER_NAME_VERSION} is not exists, Creating && Install "
        { ## try
          tar -zxf $PROGDIR/package/${!SERVER_NAME_PACKAGE} -C $HADOOP_DIR/ &&
          echo "export ${SERVER_NAME}_HOME=$HADOOP_DIR/${!SERVER_NAME_VERSION}" >> $HADOOP_DIR/.bash_profile &&
          echo 'export PATH=$'"${SERVER_NAME}"'_HOME/bin:$PATH' >> $HADOOP_DIR/.bash_profile &&
          source $HADOOP_DIR/.bash_profile &&
          
          ## you codes
          ## 修改配置文件
          SERVER_CONF_DIR=$HADOOP_DIR/${!SERVER_NAME_VERSION}/conf &&
          
          STATE=1
        } || { ## catch
          STATE=2
        }
      else
        STATE=3
      fi
    fi
  done

  ## 判断主机是否安装完成
  checkState $SERVER_NAME $STATE
}

## 安装JDK 1.8,设置环境变量
function installJDK(){
  SERVER_NAME="JDK"
  source $PROGDIR/conf/init.cfg
  format_print INFO "########## 安装 $SERVER_NAME"
  format_print INFO "${SERVER_NAME}_HOSTS Is : ${!SERVER_NAME_HOSTS}"

  ## 判断服务对应的主机是否配置
  if [[ ! -n ${!SERVER_NAME_HOSTS} ]];then
    format_print INFO "${SERVER_NAME}_HOSTS not set"
  fi

  ## 判断主机是否需要安装
  STATE=0
  for HOST in ${!SERVER_NAME_HOSTS}
  do
    if [[ $HOSTNAME == $HOST ]];then
      format_print INFO "$HOSTNAME 需要安装 $SERVER_NAME"
      if [[ ! -d $HADOOP_DIR/${!SERVER_NAME_VERSION} ]];then
        format_print INFO "$HADOOP_DIR/${!SERVER_NAME_VERSION} is not exists, Creating && Install "
        { ## try
          tar -zxf $PROGDIR/package/${!SERVER_NAME_PACKAGE} -C $HADOOP_DIR/ &&
          echo "export ${SERVER_NAME}_HOME=$HADOOP_DIR/${!SERVER_NAME_VERSION}" >> $HADOOP_DIR/.bash_profile &&
          echo 'export PATH=$'"${SERVER_NAME}"'_HOME/bin:$PATH' >> $HADOOP_DIR/.bash_profile &&
          source $HADOOP_DIR/.bash_profile &&
          
          java -version &&
          STATE=1
        } || { ## catch
          STATE=2
        }
      else
        STATE=3
      fi
    fi
  done

  ## 判断主机是否安装完成
  checkState $SERVER_NAME $STATE
}

## 安装 Zookeeper,设置环境变量
function installZOOKEEPER(){
  SERVER_NAME="ZOOKEEPER"
  source $PROGDIR/conf/init.cfg
  format_print INFO "########## 安装 $SERVER_NAME"
  format_print INFO "${SERVER_NAME}_HOSTS Is : ${!SERVER_NAME_HOSTS}"

  ## 判断服务对应的主机是否配置
  if [[ ! -n ${!SERVER_NAME_HOSTS} ]];then
    format_print INFO "${SERVER_NAME}_HOSTS not set"
  fi

  ## 判断主机是否需要安装
  STATE=0
  for HOST in ${!SERVER_NAME_HOSTS}
  do
    if [[ $HOSTNAME == $HOST ]];then
      format_print INFO "$HOSTNAME 需要安装 $SERVER_NAME"
      if [[ ! -d $HADOOP_DIR/${!SERVER_NAME_VERSION} ]];then
        format_print INFO "$HADOOP_DIR/${!SERVER_NAME_VERSION} is not exists, Creating && Install "
        { ## try
          tar -zxf $PROGDIR/package/${!SERVER_NAME_PACKAGE} -C $HADOOP_DIR/ &&
          DATA_DIR=$HADOOP_DIR/${!SERVER_NAME_VERSION}/data &&
          LOG_DIR=$HADOOP_DIR/${!SERVER_NAME_VERSION}/log &&
          mkdir $DATA_DIR &&
          mkdir $LOG_DIR &&
          
          ## 配置环境变量
          echo "export ${SERVER_NAME}_HOME=$HADOOP_DIR/${!SERVER_NAME_VERSION}" >> $HADOOP_DIR/.bash_profile &&
          echo 'export PATH=$'"${SERVER_NAME}"'_HOME/bin:$PATH' >> $HADOOP_DIR/.bash_profile &&
          source $HADOOP_DIR/.bash_profile &&
          
          ## 修改配置文件
          SERVER_CONF_DIR=$HADOOP_DIR/${!SERVER_NAME_VERSION}/conf &&
          echo "tickTime=2000" > $SERVER_CONF_DIR/zoo.cfg &&
          echo "initLimit=10" >> $SERVER_CONF_DIR/zoo.cfg &&
          echo "syncLimit=5" >> $SERVER_CONF_DIR/zoo.cfg &&
          echo "dataDir=$DATA_DIR" >> $SERVER_CONF_DIR/zoo.cfg &&
          echo "dataLogDir=$LOG_DIR" >> $SERVER_CONF_DIR/zoo.cfg &&
          echo "clientPort=2181" >> $SERVER_CONF_DIR/zoo.cfg &&
          echo "autopurge.snapRetainCount=3" >> $SERVER_CONF_DIR/zoo.cfg &&
          echo "autopurge.purgeInterval=1" >> $SERVER_CONF_DIR/zoo.cfg &&
          
          for ((i=0;i<${#ZOOKEEPER_HOSTS[@]};i++))
          do
            echo "server.$i=${ZOOKEEPER_HOSTS[$i]}:2888:3888" >> $SERVER_CONF_DIR/zoo.cfg
            if [[ $HOSTNAME == ${ZOOKEEPER_HOSTS[$i]} ]];then
              echo $i > $DATA_DIR/myid
            fi
          done &&
          STATE=1
        } || { ## catch
          STATE=2
        }
      else
        STATE=3
      fi
    fi
  done

  ## 判断主机是否安装完成
  checkState $SERVER_NAME $STATE
}

## 安装 Hadoop,设置环境变量
function installHADOOP(){
  SERVER_NAME="HADOOP"
  source $PROGDIR/conf/init.cfg
  format_print INFO "########## 安装 $SERVER_NAME"
  format_print INFO "${SERVER_NAME}_HOSTS Is : ${!SERVER_NAME_HOSTS}"

  ## 判断服务对应的主机是否配置
  if [[ ! -n ${!SERVER_NAME_HOSTS} ]];then
    format_print INFO "${SERVER_NAME}_HOSTS not set"
  fi

  ## 判断主机是否需要安装
  STATE=0
  for HOST in ${!SERVER_NAME_HOSTS}
  do
    if [[ $HOSTNAME == $HOST ]];then
      format_print INFO "$HOSTNAME 需要安装 $SERVER_NAME"
      if [[ ! -d $HADOOP_DIR/${!SERVER_NAME_VERSION} ]];then
        format_print INFO "$HADOOP_DIR/${!SERVER_NAME_VERSION} is not exists, Creating && Install "
        { ## try
          tar -zxf $PROGDIR/package/${!SERVER_NAME_PACKAGE} -C $HADOOP_DIR/ &&
          ## 配置环境变量
          echo "export ${SERVER_NAME}_HOME=$HADOOP_DIR/${!SERVER_NAME_VERSION}" >> $HADOOP_DIR/.bash_profile &&
          echo 'export PATH=$'"${SERVER_NAME}"'_HOME/bin:$'"${SERVER_NAME}"'_HOME/sbin:$PATH' >> $HADOOP_DIR/.bash_profile &&
          source $HADOOP_DIR/.bash_profile &&

          ## 修改配置文件
          SERVER_CONF_DIR=$HADOOP_DIR/${!SERVER_NAME_VERSION}/etc/hadoop &&
          cat $PROGDIR/conf/core-site.xml > $SERVER_CONF_DIR/core-site.xml &&
          sed -i "s/HDFS_MASTER/$HDFS_MASTER/g" $SERVER_CONF_DIR/core-site.xml &&
          sed -i "s|tmp_dir|$HADOOP_DIR\/${!SERVER_NAME_VERSION}\/tmp|g" $SERVER_CONF_DIR/core-site.xml &&

          cat $PROGDIR/conf/hdfs-site.xml > $SERVER_CONF_DIR/hdfs-site.xml &&
          sed -i "s/HDFS_MASTER/$HDFS_MASTER/g" $SERVER_CONF_DIR/hdfs-site.xml &&
          sed -i "s|name_dir|file\:$HADOOP_DIR\/${!SERVER_NAME_VERSION}\/dfs\/name|g" $SERVER_CONF_DIR/hdfs-site.xml &&
          sed -i "s|data_dir|file\:$HADOOP_DIR\/${!SERVER_NAME_VERSION}\/dfs\/data|g" $SERVER_CONF_DIR/hdfs-site.xml &&
          if [[ ${#HADOOP_HOSTS[@]} == 1 ]];then
            sed -i "s/dfs_rep/1/g" $SERVER_CONF_DIR/hdfs-site.xml
          else
            sed -i "s/dfs_rep/2/g" $SERVER_CONF_DIR/hdfs-site.xml
          fi &&
          
          ## 设置Hadoop 的 JAVA_HOME
          sed -i 's|JAVA_HOME=${JAVA_HOME}|'"JAVA_HOME=$HADOOP_DIR/$JDK_VERSION"'|g' $SERVER_CONF_DIR/hadoop-env.sh  &&
          
          sed "s/HDFS_MASTER/$HDFS_MASTER/g" $PROGDIR/conf/yarn-site.xml > $SERVER_CONF_DIR/yarn-site.xml &&
          sed "s/HDFS_MASTER/$HDFS_MASTER/g" $PROGDIR/conf/mapred-site.xml > $SERVER_CONF_DIR/mapred-site.xml &&
          sed -i "s|CLASSPATH|`hadoop classpath`|g" $SERVER_CONF_DIR/yarn-site.xml &&
          sed -i "s|CLASSPATH|`hadoop classpath`|g" $SERVER_CONF_DIR/mapred-site.xml &&
          
          > $SERVER_CONF_DIR/slaves &&
          for i in ${!SERVER_NAME_HOSTS}
          do
            echo "$i" >> $SERVER_CONF_DIR/slaves
          done &&
          cat $SERVER_CONF_DIR/slaves > $SERVER_CONF_DIR/workers

          $HADOOP_DIR/${!SERVER_NAME_VERSION}/bin/hadoop version &&
          STATE=1
        } || { ## catch
          STATE=2
        }
      else
        STATE=3
      fi
    fi
  done

  ## 判断主机是否安装完成
  checkState $SERVER_NAME $STATE
}

## 安装 Hive,设置环境变量
function installHIVE(){
  SERVER_NAME="HIVE"
  source $PROGDIR/conf/init.cfg
  format_print INFO "########## 安装 $SERVER_NAME"
  format_print INFO "${SERVER_NAME}_HOSTS Is : ${!SERVER_NAME_HOSTS}"

  ## 判断服务对应的主机是否配置
  if [[ ! -n ${!SERVER_NAME_HOSTS} ]];then
    format_print INFO "${SERVER_NAME}_HOSTS not set"
  fi

  ## 判断主机是否需要安装
  STATE=0
  for HOST in ${!SERVER_NAME_HOSTS}
  do
    if [[ $HOSTNAME == $HOST ]];then
      format_print INFO "$HOSTNAME 需要安装 $SERVER_NAME"

      if [[ ! -d $HADOOP_DIR/${!SERVER_NAME_VERSION} ]];then
        format_print INFO "$HADOOP_DIR/${!SERVER_NAME_VERSION} is not exists, Creating && Install "
        { ## try
          tar -zxf $PROGDIR/package/${!SERVER_NAME_PACKAGE} -C $HADOOP_DIR/ &&
          ## 配置环境变量
          echo "export ${SERVER_NAME}_HOME=$HADOOP_DIR/${!SERVER_NAME_VERSION}" >> $HADOOP_DIR/.bash_profile &&
          echo 'export PATH=$'"${SERVER_NAME}"'_HOME/bin:$PATH' >> $HADOOP_DIR/.bash_profile &&
          source $HADOOP_DIR/.bash_profile &&
          
          ## 修改配置文件
          SERVER_CONF_DIR=$HADOOP_DIR/${!SERVER_NAME_VERSION}/conf &&
          cat $PROGDIR/conf/hive-site.xml > $SERVER_CONF_DIR/hive-site.xml &&
          sed -i "s/HDFS_MASTER/$HDFS_MASTER/g" $SERVER_CONF_DIR/hive-site.xml &&
          sed -i "s/HDFS_NODE/$HOSTNAME/g" $SERVER_CONF_DIR/hive-site.xml &&
          cp $PROGDIR/package/mysql-connector-java-8.0.11.jar $HADOOP_DIR/${!SERVER_NAME_VERSION}/lib/ &&

          $HADOOP_DIR/${!SERVER_NAME_VERSION}/bin/hive --version &&
          STATE=1
        } || { ## catch
          STATE=2
        }
      else
        STATE=3
      fi
    fi
  done

  ## 判断主机是否安装完成
  checkState $SERVER_NAME $STATE
}

## 安装 Spark ,设置环境变量
function installSPARK(){
  SERVER_NAME="SPARK"
  source $PROGDIR/conf/init.cfg
  format_print INFO "########## 安装 $SERVER_NAME"
  format_print INFO "${SERVER_NAME}_HOSTS Is : ${!SERVER_NAME_HOSTS}"

  ## 判断服务对应的主机是否配置
  if [[ ! -n ${!SERVER_NAME_HOSTS} ]];then
    format_print INFO "${SERVER_NAME}_HOSTS not set"
  fi

  ## 判断主机是否需要安装
  STATE=0
  for HOST in ${!SERVER_NAME_HOSTS}
  do
    if [[ $HOSTNAME == $HOST ]];then
      format_print INFO "$HOSTNAME 需要安装 $SERVER_NAME"
      if [[ ! -d $HADOOP_DIR/${!SERVER_NAME_VERSION} ]];then
        format_print INFO "$HADOOP_DIR/${!SERVER_NAME_VERSION} is not exists, Creating && Install "
        { ## try
          tar -zxf $PROGDIR/package/${!SERVER_NAME_PACKAGE} -C $HADOOP_DIR/ &&
          echo "export ${SERVER_NAME}_HOME=$HADOOP_DIR/${!SERVER_NAME_VERSION}" >> $HADOOP_DIR/.bash_profile &&
          echo 'export PATH=$'"${SERVER_NAME}"'_HOME/bin:$PATH' >> $HADOOP_DIR/.bash_profile &&
          source $HADOOP_DIR/.bash_profile &&
          
          ## 修改配置文件
          SERVER_CONF_DIR=$HADOOP_DIR/${!SERVER_NAME_VERSION}/conf &&
          cp ${HADOOP_HOME}/etc/hadoop/core-site.xml $SERVER_CONF_DIR/ &&
          cp ${HADOOP_HOME}/etc/hadoop/hdfs-site.xml $SERVER_CONF_DIR/ &&
          cp ${HADOOP_HOME}/etc/hadoop/yarn-site.xml $SERVER_CONF_DIR/ &&
          cp ${HIVE_HOME}/conf/hive-site.xml $SERVER_CONF_DIR/ &&
          
          echo "# Spark on Yarn" > $SERVER_CONF_DIR/spark-env.sh &&
          echo "SPARK_CONF_DIR=${SPARK_HOME}/conf" > $SERVER_CONF_DIR/spark-env.sh &&
          echo "HADOOP_CONF_DIR=${HADOOP_HOME}/etc/hadoop" > $SERVER_CONF_DIR/spark-env.sh &&
          echo "YARN_CONF_DIR=${HADOOP_HOME}/etc/hadoop" > $SERVER_CONF_DIR/spark-env.sh &&
          STATE=1
        } || { ## catch
          STATE=2
        }
      else
        STATE=3
      fi
    fi
  done

  ## 判断主机是否安装完成
  checkState $SERVER_NAME $STATE
}

## 安装 HBASE,设置环境变量
function installHBASE(){
  SERVER_NAME="HBASE"
  source $PROGDIR/conf/init.cfg
  format_print INFO "########## 安装 $SERVER_NAME"
  format_print INFO "${SERVER_NAME}_HOSTS Is : ${!SERVER_NAME_HOSTS}"

  ## 判断服务对应的主机是否配置
  if [[ ! -n ${!SERVER_NAME_HOSTS} ]];then
    format_print INFO "${SERVER_NAME}_HOSTS not set"
  fi

  ## 判断主机是否需要安装
  STATE=0
  for HOST in ${!SERVER_NAME_HOSTS}
  do
    if [[ $HOSTNAME == $HOST ]];then
      format_print INFO "$HOSTNAME 需要安装 $SERVER_NAME"
      if [[ ! -d $HADOOP_DIR/${!SERVER_NAME_VERSION} ]];then
        format_print INFO "$HADOOP_DIR/${!SERVER_NAME_VERSION} is not exists, Creating && Install "
        { ## try
          tar -zxf $PROGDIR/package/${!SERVER_NAME_PACKAGE} -C $HADOOP_DIR/ &&
          echo "export ${SERVER_NAME}_HOME=$HADOOP_DIR/${!SERVER_NAME_VERSION}" >> $HADOOP_DIR/.bash_profile &&
          echo 'export PATH=$'"${SERVER_NAME}"'_HOME/bin:$PATH' >> $HADOOP_DIR/.bash_profile &&
          source $HADOOP_DIR/.bash_profile &&

          ## 修改配置文件
          SERVER_CONF_DIR=$HADOOP_DIR/${!SERVER_NAME_VERSION}/conf &&
          cat $PROGDIR/conf/hbase-site.xml > $SERVER_CONF_DIR/hbase-site.xml &&
          sed -i "s/HDFS_MASTER/$HDFS_MASTER/g" $SERVER_CONF_DIR/hbase-site.xml &&
          sed -i "s|HBASE_HOME|$HADOOP_DIR/$HBASE_VERSION|g" $SERVER_CONF_DIR/hbase-site.xml &&
          sed -i "s|ZOOKEEPER_HOME|$HADOOP_DIR/$ZOOKEEPER_VERSION|g" $SERVER_CONF_DIR/hbase-site.xml &&
          sed -i "s|ZOOKEEPER_HOSTS|`echo ${ZOOKEEPER_HOSTS[*]} | sed 's/ /,/g'`|g" $SERVER_CONF_DIR/hbase-site.xml &&

          cat $PROGDIR/conf/hbase-env.sh > $SERVER_CONF_DIR/hbase-env.sh &&
          sed -i "s|JAVA_DIR|$HADOOP_DIR/$JAVA_VERSION|g" $SERVER_CONF_DIR/hbase-env.sh &&
          sed -i "s|HBASE_HOME|$HADOOP_DIR/$HBASE_VERSION|g" $SERVER_CONF_DIR/hbase-env.sh &&
          
          > $SERVER_CONF_DIR/regionservers &&
          for i in ${!SERVER_NAME_HOSTS}
          do
            echo "$i" >> $SERVER_CONF_DIR/regionservers
          done &&
          
          STATE=1
        } || { ## catch
          STATE=2
        }
      else
        STATE=3
      fi
    fi
  done
}

installJDK
installZOOKEEPER
installHADOOP
installHIVE
installSPARK
installHBASE
